package cn.iocoder.yudao.module.mqtt.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * version 1.0
 * @author CY_Guo
 * @date 2025/7/30 11:31
 * disk 磁盘数据 ， cpu cpu数据 ， memory 内存数据
 */
public class SysInfoUtil {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 获取系统资源使用率，用于前端扇形图展示。
     * 此方法为公共静态方法，可被 Controller 直接调用。
     *
     * @return JSON格式的字符串，包含CPU、内存、磁盘的使用率数据。
     *         格式如: {"cpu":{"used":2,"free":98},"memory":{"used":81,"free":19},"disk":{"used":75,"free":25}}
     *         如果获取数据失败，返回一个空的JSON对象 "{}"。
     */
    public static String getSysUsageForFrontend() {
        try {
            SystemInfo si = new SystemInfo();
            HardwareAbstractionLayer hal = si.getHardware();
            OperatingSystem os = si.getOperatingSystem();

            // 获取 CPU 使用率
            CentralProcessor processor = hal.getProcessor();
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            Thread.sleep(1000); // 等待 1 秒
            double cpuLoad = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
            int cpuUsed = (int) Math.round(cpuLoad); // 四舍五入取整

            // 获取内存使用率
            GlobalMemory memory = hal.getMemory();
            long totalMemory = memory.getTotal();
            long availableMemory = memory.getAvailable();
            long usedMemory = totalMemory - availableMemory;
            double memoryUsage = (double) usedMemory / totalMemory * 100;
            int memoryUsed = (int) Math.round(memoryUsage); // 四舍五入取整

            // 获取系统盘使用率
            FileSystem fileSystem = os.getFileSystem();
            List<OSFileStore> fileStores = fileSystem.getFileStores();
            int diskUsed = 0;
            for (OSFileStore fs : fileStores) {
                if (isSystemDrive(fs)) {
                    long totalSpace = fs.getTotalSpace();
                    long freeSpace = fs.getUsableSpace();
                    long usedSpace = totalSpace - freeSpace;
                    double diskUsage = (double) usedSpace / totalSpace * 100;
                    diskUsed = (int) Math.round(diskUsage); // 四舍五入取整
                    break;
                }
            }

            // 封装数据
            Map<String, Object> result = new HashMap<>();
            result.put("cpu", getFanChartData(cpuUsed, "已用", "空闲"));
            result.put("memory", getFanChartData(memoryUsed, "已用", "空闲"));
            result.put("disk", getFanChartData(diskUsed, "已用", "可用"));

            // 转换为 JSON 字符串并返回
            return objectMapper.writeValueAsString(result);

        } catch (Exception e) {
            // 捕获所有异常，如线程中断、OSHI内部错误等，保证Controller调用不会抛出500错误
            e.printStackTrace(); // 建议在生产环境使用日志框架记录
            // 返回一个安全的默认值
            return "{}";
        }
    }

    /**
     * 辅助方法：根据使用率生成扇形图所需的数据结构。
     */
    private static Map<String, Object> getFanChartData(int usage, String usedLabel, String freeLabel) {
        Map<String, Object> data = new HashMap<>();
        data.put("used", usage);
        data.put("free", 100 - usage);
        return data;
    }

    /**
     * 判断是否是系统盘
     */
    private static boolean isSystemDrive(OSFileStore fs) {
        String mount = fs.getMount();
        // Linux: 根目录或 /boot
        if ("/".equals(mount) || mount.startsWith("/boot")) {
            return true;
        }
        // Windows: C:\
        if (mount != null && mount.toUpperCase().startsWith("C:\\")) {
            return true;
        }
        return false;
    }

    // ------------------ 以下是用于测试的 main 方法 ------------------
    public static void main(String[] args) {
        String jsonData = getSysUsageForFrontend();
        System.out.println(jsonData);
    }
}